using UnityEngine;
using System.Collections;

/// <summary>
/// Gestor camino. Encargado de recibir por el editor las aristas pertinentes y mover al personaje por el camino trazado.
/// </summary>
/// <author>
/// José Antonio Perales Chía.
/// </author>
public class Camino : MonoBehaviour {
	
	
	
	//Parámetros públicos
	
	public Linea[] listadoLineas;
	
	public bool pathEnabled;
	
	
	/// <summary>
	/// Tipo camino. Esta propiedad la usa otro script: indica si el camino elegido es correcto o no.
	/// </summary>
	public enum tipoCamino {malo, bueno};
	public tipoCamino elCaminoEs;
	
	
	//Parámetros privados
	
	/// <summary>
	/// El number de lineas que compone el camino, tanto rectas como curvas
	/// </summary>
	private int numLineas;
	/// <summary>
	/// La longitud que devuelve la función Length(). Esta variable existe para que se acumule de forma estática dicha longitud y no tener que estar calculandola
	/// cada iteración. Ahorra proceso
	/// </summary>/
	private float length;
	
	/// <summary>
	/// Aqui acumularemos las distancias de principio y fin de cada linea respecto del inicio, de forma que no tengamos que estar calculandolas posteriormente
	/// </summary>
	private float[,] Distancias;
	
	/// <summary>
	/// Variable que guarda el segmento actual donde se encuentra el punto que se está calculando. Uso interno
	/// </summary>
	private int segment;
	
	/// <summary>
	/// Awake this instance. Usamos Awake para que otros Scripts puedan arrancar con Start() sin problemas de dependencias.
	/// </summary>
	void Awake () {
		
		numLineas = listadoLineas.GetLength(0);	//numero de lineas que hay en el camino. Para operaciones internas.
		length = Length; //Longitud total del camino.
		
		//Rellenamos el vector Distancias.
		Distancias = new float[numLineas,2];
		
		for (int i=0;i<numLineas;i++)
		{
			Distancias[i,0]= DistanceLineStarts(i);
			Distancias[i,1]= DistanceLineEnds(i);
		}
		
		segment=0;
		
		
	}
	
	//Batería de propiedades
	
	/// <summary>
	/// Devuelve el punto de comienzo del camino.
	/// </summary>
	/// <value>
	/// The start point.
	/// </value>
	public Vector3 StartPoint
	{
		get{ return CalculatePathPoint(0); }	
	}
	
	/// <summary>
	/// Devuelve el último punto del camino.
	/// </summary>
	/// <value>
	/// The last point.
	/// </value>
	public Vector3 LastPoint
	{
		get{ return CalculatePathPoint(length);}
	}
	
	/// <summary>
	/// Calcula la longitud del camino completo
	/// </summary>
	public float Length
	{
		get{
			float auxLenght=0;
			for(int i=0;i<numLineas;i++)
				auxLenght += listadoLineas[i].StaticLenght;

			return auxLenght;
		}
	}
	
	/// <summary>
	/// Devuelve la longitud del camino con su configuración inicial. Si modificamos la longitud del camino este valor será incorrecto.
	/// </summary>
	/// <value>
	/// Longitud del camino.
	/// </value>
	public float NotDinamicLength
	{
		get {return length;}
	}

	/*void OnGUI () 
	{
		
			GUI.Label (new Rect (25, 10, 400, 30), "Longitud Total del camino: " + length);
		
			for(int i=0;i<numLineas;i++)
			{
			GUI.Label (new Rect (25, 30+25*i, 300, 20), "Longitud del tramo [" + i + "]: "  + listadoLineas[i].StaticLenght);
			GUI.Label (new Rect (400, 30+25*i, 300, 20), "Donde empieza [" + i + "]: "  + DistanceLineEnds(i));
			
			}
			
			
	}*/
	
	
	/// <summary>
	/// Pasandole la distancia real de la linea en cuestion nos dice a que distancia se encuentra su primer punto respecto principios.
	/// </summary>
	/// <returns>
	/// Distancia a la que comienza el segmento respecto del total
	/// </returns>
	/// <param name='segment'>
	/// El Segmento
	/// </param>
	float DistanceLineStarts(int segment)
	{
		if (segment>=1 && segment<=numLineas)
		{
			float auxLength=0;
			for (int i=0; i<segment;i++)
				auxLength+= listadoLineas[i].StaticLenght;
			return auxLength;
		}
		return 0f;
	}
	

	/// <summary>
	/// Pasandole la distancia real de la linea en cuestion nos dice a que distancia se encuentra su ultimo punto respecto principios.
	/// </summary>
	/// <returns>
	/// Distancia a la que acaba el segmento respecto del total
	/// </returns>
	/// <param name='segment'>
	/// El Segmento
	/// </param>
	float DistanceLineEnds(int segment)
	{
		if (segment>=0 && segment<=numLineas)
		{
			float auxLength=0;
			for (int i=0; i<=segment;i++)
				auxLength+= listadoLineas[i].StaticLenght;
			return auxLength;
		}
		return 0f;
	}
	
	//Como DistanceLineStarts pero acotado entre 0 y 1
	float Distance01LineStarts(int segment)
	{
		return DistanceLineStarts(segment)/length;
	}
	
	//Como DistanceLineEnds pero acotado entre 0 y 1
	float Distance01LineEnds(int segment)
	{
		return DistanceLineEnds(segment)/length;
	}
	
	/// <summary>
	/// Calculates the path point.
	/// </summary>
	/// <returns>
	/// The path point.
	/// </returns>
	/// <param name='distance'>
	/// Distance.
	/// </param>
	public Vector3 CalculatePathPoint(float distance)
	{ 	
		//ponemos esta condicion para no llamar a WhereSegmentPointIs cuando no haga falta
		if (distance<Distancias[segment,0] || distance>Distancias[segment,1]) 
			segment = WhereSegmentPointIs(distance);
		
		
		return listadoLineas[segment].CalculatePointTo01(distance-Distancias[segment,0]);
		
	}
	
	/// <summary>
	/// indica en que segmento se encuentra la distancia que buscamos.
	/// </summary>
	/// <returns>
	/// The segment point
	/// </returns>
	/// <param name='distance'>
	/// La distancia actual a la que se encuentra el punto del principio.
	/// </param>
	int WhereSegmentPointIs(float distance)
	{
		int segment=0;
		for(int i=0;i<numLineas;i++)
			if(distance>=Distancias[i,0] && distance<=Distancias[i,1])
			{
				segment=i; break;
			}
		return segment;
	}
	
	
	
}
